/**
 * Copyright (C) 2009 Noel Ang
 *
 * This file is part of Samsara.
 *
 * Samsara is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Samsara is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Samsara.  If not, see <http://www.gnu.org/licenses/>.
 ******************************************************************************/
package com.lunarshades.samsara.ui.actions;

import java.awt.Font;
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.ClipboardOwner;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.util.Set;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.event.CaretEvent;
import javax.swing.event.CaretListener;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.TableModel;

import com.lunarshades.samsara.Raider;
import com.lunarshades.samsara.ui.RosterTableModel;
import com.lunarshades.samsara.ui.SamsaraFrame;

/**
 * Action responsible for exporting data from a RosterTableModel to a
 * particular format.  This implementation exports data in UBB-compatible code.
 *
 * @author Noel Ang, sparta.variable@gmail.com
 * @see com.lunarshades.samsara.ui.RosterTableModel
 */
public class RosterExportAction extends AbstractAction
        implements TableModelListener, ClipboardOwner {

public RosterExportAction(RosterTableModel<? extends Raider> model,
                          SamsaraFrame app
) {
    super(NAME);

    mApp = app;
    mModel = model;
    putValue(Action.MNEMONIC_KEY, KeyEvent.VK_U);
    putValue(Action.SHORT_DESCRIPTION, SHORT_TEXT);
    setEnabled(false);

    mModel.addTableModelListener(this);
}

private boolean isMySubject(Object obj) {
    return (obj != null && obj == mModel);
}

private boolean export() {
    final StringBuffer outputBuffer = new StringBuffer();
    boolean success = false;

    outputBuffer.append("[table]\n");
    outputBuffer.append("[tr]");
    outputBuffer.append("[td]");
    outputBuffer.append("[b]").append("NAME").append("[/b]");
    outputBuffer.append("[/td]");
    outputBuffer.append("[td]");
    outputBuffer.append("[b]").append("KARMA").append("[/b]");
    outputBuffer.append("[/td]");
    outputBuffer.append("[/tr]\n");
    synchronized (mModel) {
        for (Raider raider : mModel.sortedSet()) {
            // Exclude pick-ups
            if (raider.pickup()) {
                continue;
            }
            outputBuffer.append("[tr]");
            outputBuffer.append("[td]");

            String primaryName = raider.id();
            Set<String> allNames = raider.names();
            outputBuffer.append(primaryName);
            if (allNames.size() > 1) {
                for (String name : allNames) {
                    if (!name.equalsIgnoreCase(primaryName)) {
                        outputBuffer.append('/');
                        outputBuffer.append(name);
                    }
                }
            }
            
            outputBuffer.append("[/td]");
            outputBuffer.append("[td]");
            outputBuffer.append(raider.karma());
            outputBuffer.append("[/td]");
            outputBuffer.append("[/tr]\n");
        }
    }
    outputBuffer.append("[/table]");

    display(outputBuffer.toString());

    return success;
}

private void display(String data) {

    if (mScrollPane == null) {
        Font font = Font.decode(Font.DIALOG).deriveFont(Font.PLAIN, 10.0F);
        mTextArea = new JTextArea();
        mTextArea.setEditable(false);
        mTextArea.setEnabled(true);
        mTextArea.setFocusable(true);
        mTextArea.setLineWrap(true);
        mTextArea.setWrapStyleWord(true);
        mTextArea.addCaretListener(new CaretListenerImpl());
        mTextArea.setFont(font);
        mTextArea.setRows(ROWS);
        mScrollPane = new JScrollPane(mTextArea,
                JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
                JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED
        );
    }

    mTextArea.setText(data);
    mTextArea.setSelectionStart(0);
    mTextArea.setSelectionEnd(mTextArea.getDocument()
            .getEndPosition().getOffset()
    );

    // Copy to clipboard
    try {
        StringSelection fragment = new StringSelection(data);
        Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
        clipboard.setContents(fragment, this);
    } catch (IllegalStateException ignored) {
    }

    JOptionPane.showMessageDialog(SwingUtilities.windowForComponent(mScrollPane),
            mScrollPane,
            OUTPUT_TITLE,
            JOptionPane.PLAIN_MESSAGE
    );
}

public void actionPerformed(ActionEvent ignored) {
    if (export()) {
        mApp.postStatusMessage(SUCCESS_STATUS);
    } else {
        mApp.postStatusMessage(FAILED_STATUS);
    }
}

public void tableChanged(TableModelEvent e) {
    Object source = e.getSource();
    if (isMySubject(source)) {
        setEnabled(((TableModel) source).getRowCount() != 0);
    }
}

public void lostOwnership(Clipboard clipboard, Transferable contents) {
    // Do nothing
}

private class CaretListenerImpl implements CaretListener {
    public void caretUpdate(CaretEvent e) {
        Object source = e.getSource();
        if (source != null && source instanceof JTextArea) {
            JTextArea area = (JTextArea) source;
            area.removeCaretListener(this);
            area.setSelectionStart(0);
            area.setSelectionEnd(area.getDocument()
                    .getEndPosition().getOffset()
            );
            area.addCaretListener(this);
        }
    }
}

private static final String NAME = "UBB code";
private static final String SHORT_TEXT = "Export data set in UBB table form";
private static final String OUTPUT_TITLE = "UBB Code Export";
private static final String SUCCESS_STATUS = "Export successful.";
private static final String FAILED_STATUS = "Export canceled.";
private static final int ROWS = 28;
private final SamsaraFrame mApp;
private final RosterTableModel<?> mModel;
private volatile JTextArea mTextArea;
private volatile JScrollPane mScrollPane;
}
